<template>
  <div class="department-container">
    <div class="app-container">
      <!-- 面板结构 -->
      <el-card>
        <!-- 头部 -->
        <!-- 行列布局：栅格布局，将一行分为 24 份，每列占多少份由 el-col 身上的 span 属性决定。 -->
        <!-- type：flex 启用弹性布局。默认是使用的浮动布局 -->
        <!-- justify：flex 布局下的水平排列方式 -->
        <!-- align：flex 布局下的垂直排列方式 -->
        <treeTools :item="company" :is-root="true" @showEdit="showEdit" />
        <!-- 自定义 -->
        <!-- data是树形组件的传入的数据 是一个数组 带有层级关系 (通过children体现) -->
        <!-- show-checkbox节点是否可被选择 -->
        <!-- node-key每个树节点用来作为唯一标识的属性，整棵树应该是唯一的类似于v-for中的key -->
        <!-- default-expand-all否默认展开所有节点 -->
        <!-- expand-on-click-node 点击箭头 还是点击文字用于收起展开 -->
        <!-- el-tree对于传入的数据的键名有固定要求 默认用于显示的字段 label  -->
        <!-- 默认用于显示层级的字段键名只能为children -->
        <!-- props 是一个对象 在对象中可以配置 树形组件用于渲染文字的字段名 label
        也可以配置 树形组件用于定义层级关系的字段名 children -->
        <el-tree
          :data="list"
          node-key="id"
          default-expand-all
          :props="defaultProps"
        >
          <!-- 作用域插槽 -->
          <!-- node：el-tree 底层的节点信息 -->
          <!-- data：拿到的是每个节点的数据对象 -->
          <template #default="{ data }">
            <treeTools :item="data" @showEdit="showEdit" @editDepartment="editDepartment" />
          </template>
        </el-tree>
      </el-card>
      <!-- <button @click="finddChildren(list,'604e2251b205b95968e1312c')">找子元素</button>  -->
    </div>
    <!-- 弹框 -->
    <el-dialog
      :title="title"
      :visible="dialogVisible"
      width="30%"
      @close="closeDialog"
    >
      <el-form ref="formRef" :model="form" :rules="rules" label-width="100px">

        <el-form-item label="部门名称" prop="name">
          <el-input v-model="form.name" placeholder="1-50个字符" />
        </el-form-item>

        <el-form-item label="部门编码" prop="code">
          <el-input v-model="form.code" placeholder="1-50个字符" />
        </el-form-item>

        <el-form-item label="部门负责人" prop="manager">
          <el-select v-model="form.manager" placeholder="请选择">
            <el-option
              v-for="item in employeeList"
              :key="item.id"
              :label="item.username"
              :value="item.username"
            />
          </el-select>
        </el-form-item>
        <el-form-item label="部门介绍" prop="introduce">
          <el-input v-model="form.introduce" type="textarea" placeholder="1-300字符" />
        </el-form-item>

      </el-form>
      <span slot="footer" class="dialog-footer">
        <el-button @click="dialogVisible = false">取 消</el-button>
        <el-button type="primary" @click="submit">确 定</el-button>
      </span>
    </el-dialog>
  </div>
</template>
<script>
import treeTools from '@/views/Department/components/tree-tools'
import { getDepartmentList, getSimplList, addDepartment, getDetailById, updateDepartment, delDetailById } from '@/api'
// import transTree from '@/utils/transTree'
// import { Logger } from 'runjs/lib/common'
export default {
  name: 'Department',
  components: {
    treeTools
  },
  data() {
    // 自定义校验
    // 部门中不能新增相同的子部门
    var validateName = (rule, value, caliback) => {
      let broArr = []
      // 在编辑中，部门名称不能和他们兄弟名字一样
      if (this.form.id) {
        // 在编辑中
        if (value === this.currentNode.name) {
          // 没有任何修改，直接
          caliback()
        } else {
          // 将两者数据进行id过滤校验
          // 修改了内容
          // 如果编辑找的是当前节点的兄弟节点
          broArr = this.rowList.filter(item => item.pid === this.currentNode.pid)
        }
      } else {
        // 将两者数据进行id过滤校验
        // 如果是新增子部门，找到当前节点的子节点才是新增子部门的 兄弟节点
        broArr = this.rowList.filter(item => item.pid === this.currentNode.id)
      }

      // 获取写的数据和存的数据对比
      const isSome = broArr.some(item => item.name === value)
      // 相同则提示，不同则可继续
      if (isSome) {
        return caliback(new Error('名字重复'))
      } else {
        caliback()
      }
    }
    // 部门中不能出现重复的部门编码
    var validateCode = (rule, value, caliback) => {
      // 此时需要回复校验
      if (this.form.id && value === this.currentNode.code) {
        caliback()
      } else {
        const isSome = this.rowList.some(item => item.code === value)
        // 相同则提示，不同则可继续
        if (isSome) {
          return caliback(new Error('部门编号重复'))
        } else {
          caliback()
        }
      }
    }
    return {
      defaultProps: {
        label: 'name',
        children: 'children'
      },
      company: {
        name: '传智播客',
        manager: '负责人',
        id: ''
      },
      list: [],
      dialogVisible: false,
      form: {
        name: '',
        code: '',
        manager: '',
        introduce: ''
      },
      rules: {
        name: [
          { required: true, message: '部门名称必填', trigger: ['blur', 'change'] },
          { min: 1, max: 50, message: '部门编码要求1-50个字符', trigger: ['blur', 'change'] },
          // 自定义
          { validator: validateName, trigger: 'blur' }
        ],
        code: [
          { required: true, message: '部门编码必填', trigger: ['blur', 'change'] },
          { min: 1, max: 50, message: '部门编码要求1-50个字符', trigger: ['blur', 'change'] },
          { validator: validateCode, trigger: 'blur' }
        ],
        manager: [
          { required: true, message: '部门负责人必填', trigger: ['blur', 'change'] }
        ],
        introduce: [
          { required: true, message: '部门介绍必填', trigger: ['blur', 'change'] },
          { min: 1, max: 300, message: '部门编码要求1-300个字符', trigger: ['blur', 'change'] }
        ]
      },
      // 获取当前点击事件的触发对象
      currentNode: {},
      // 存储所有数据
      rowList: [],
      employeeList: []
    }
  },
  computed: {
    title() {
      return this.form.id ? '编辑部门' : '新增部门'
    }
  },
  created() {
    this.getList()
  },
  methods: {
    // 打开新增框
    async showEdit(item, type) {
      if (type === 'del') {
        this.$confirm('此操作将永久删除该文件, 是否继续?', '提示', {
          confirmButtonText: '确定',
          cancelButtonText: '取消',
          type: 'warning'
        }).then(async() => {
          await delDetailById(item.id)
          this.$message({
            type: 'success',
            message: '删除成功!'
          })
          this.getList()
        }).catch(() => {
          this.$message({
            type: 'info',
            message: '已取消删除'
          })
        })
        return
      }
      this.dialogVisible = true
      // console.log(item, '当前操作的节点')
      // 新建设置currentNode接受item
      this.currentNode = item
      // 调用下拉接口
      const res = await getSimplList()
      this.employeeList = res.data
    },
    // 关闭框
    closeDialog() {
      this.dialogVisible = false
      this.$refs.formRef.resetFields()
      // 收到重置
      this.form = {
        name: '',
        code: '',
        manager: '',
        introduce: ''
      }
    },
    async getList() {
      const res = await getDepartmentList()
      // console.log(res)
      this.list = this.finddChildren(res.data.depts, '')
      // 新建rowList接受数据
      this.rowList = res.data.depts
      // transTree(res.data.depts)
    },
    //     数据格式的转换
    // 1、父级的id 和子集的pid相等
    // 2、所有的pid等于 父级id的元素就应该放在父级的children中
    //     找孩子
    // 1、第一步 定义一个函数 传入 数组， 传入需要找到子节点元素的 id
    finddChildren(arr, id = '') {
      const children = []
      // 2、第二步 便利数组 找到item.pid===id的元素
      arr.forEach(item => {
        if (item.pid === id) {
          // 3、第三步 将找到的元素 放在一个名为 children的数组中
          // 树形结构的遍历和生成都需要用到递归函数
          // 因为树形结构的层级是不确定的
          // 需要一直递归到没有子节点为止递归
          // 自己调用自己
          children.push(item)
          // thisfindChildren 图数的作用是用来找到孩子放在数组中
          // 根要生成一个树形结构 需要对每一个元素查找children
          // 然后将找到的元案 放在这个item的children中
          if (children.length) {
            item.children = this.finddChildren(arr, item.id)
          }
          // 这种查找方法 必须得从根节点开始找
          // 所以后端告诉我们 数据中 p1d为空字符串的元索就是根元素
          // 所以从根节点开始资找需要在 参数的位置传入一个"
          // ·相当于 使用findChildren 查找 id为“"元素的所有子节点
        }
      })
      // console.log(children)
      return children
    },
    // 新建部门
    async submit() {
      // 1.兜底校验
      const valid = await this.$refs.formRef.validate()
      if (valid) {
        // 1.准备接口
        // 2.调用接口
        if (this.form.id) {
          // 修改
          await updateDepartment(this.form)
        } else {
          await addDepartment({
            ...this.form,
            pid: this.currentNode.id
          })
        }

        // 3.关闭弹窗
        // 4.提示用户
        this.$message.success(`${this.form.id ? '修改部门' : '新增部门'}成功`)
        // 5.刷新列表
        this.getList()
        // 6.重置并关闭表单
        this.closeDialog()
      }
    },
    // 打开弹窗 数据回显
    async editDepartment(item) {
      this.currentNode = item
      const res = await getDetailById(item.id)
      this.form = res.data
      // 第一种方法
      const res1 = await getSimplList()
      this.employeeList = res1.data
      this.dialogVisible = true
    }
  }
}
</script>

<style lang="scss" scoped>
.department-container {
  padding: 30px;
}
</style>
